﻿#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os
import yaml
import shutil

from orioluspith.packets.meta import Meta
from orioluspith.packets.metareader import FileMetaReader
from orioluspith.packets.metawriter import FileMetaWriter
from orioluspith.packets.packet import Packet
from oriolusdocker.repos.repository import Repository
from orioluspith.packets.script import Script
from StringIO import StringIO

class FileStorage:
    def __init__(self, path):
        self.__path = path
        if not os.path.exists(self.__path):
            os.mkdir(self.__path)

    def add(self, packet):
        file_name = self.__get_file_name(packet.name)
        file_path = os.path.join(self.__path, file_name)

        writer = FilePacketEntryWriter()
        writer.write(packet, file_path)

        script_writer = ScriptWriter()
        for script_name, script in packet.scripts.items():
            script_file_name = self.__get_script_file_name(packet.name, script_name)
            script_path = os.path.join(self.__path, script_file_name)
            script_writer.write(script, script_path)

    @property
    def entries(self):
        return [self.__create_packet(file_name) for file_name in self.__find_entries_by_suffix("ori.entry")]

    def remove(self, packet_name):
        packet_files = self.__find_entries_by_prefix(packet_name)
        [os.remove(file_path) for file_path in packet_files]

    def update(self, packet):
        self.remove(packet.name)
        self.add(packet)

    def __find_entries_by_suffix(self, suffix):
        filter = lambda x, y: x.endswith(y)
        file_names = self.__find_entries(filter, suffix)

        return file_names

    def __find_entries_by_prefix(self, prefix):
        filter = lambda x, y: x.startswith(y)
        file_names = self.__find_entries(filter, prefix)

        return file_names

    def __find_entries(self, filter, mask):
        entries = []
        for file_name in os.listdir(self.__path):
            if filter(file_name, mask):
                entries.append(os.path.join(self.__path, file_name))

        return entries

    def __get_file_name(self, packet_name):
        return "%s.ori.entry" % packet_name

    def __get_script_file_name(self, packet_name, script_name):
        return "%s.%s" % (packet_name, script_name)

    def __create_packet(self, packet_name):
        result_packet = FilePacketEntryReader().read(packet_name);
        resources = self.__find_entries_by_prefix(result_packet.name)
        scripts = {}
        for file_name in resources:
            if not file_name.endswith("ori.entry"):
                script = ScriptReader().read(file_name)
                scripts[script.name] = script
        return Packet(result_packet.meta, scripts, result_packet.status)
        
class PacketEntryWriter:
    def write(self, packet, file):
        stream = StringIO()

        serialized_packet_entry = {"name": packet.meta.name, "version": packet.meta.version,
            "description": packet.meta.description, "conflicts": packet.meta.conflicts,
            "replaces": packet.meta.replaces, "depends": packet.meta.depends, "status": packet.status}

        yaml.dump(serialized_packet_entry, file, default_flow_style=False)
        file.flush()

class FilePacketEntryWriter:
    def __init__(self):
        self.__file_writer = PacketEntryWriter()

    def write(self, packet, file_path):
        fd = None
        try:
            fd = file(file_path, "w")
            self.__file_writer.write(packet, fd)
        finally:
            if fd:
                fd.close()

class PacketEntryReader:
    def read(self, file):
        dict = yaml.load(file)

        return Packet(Meta(dict["name"], dict["version"], dict["description"], 
            dict["conflicts"], dict["replaces"], dict["depends"]), status=dict["status"])

class FilePacketEntryReader:
    def __init__(self):
        self.__file_reader = PacketEntryReader()

    def read(self, file_name):
        fd = None
        try:
            fd = file(file_name, "r")
            return self.__file_reader.read(fd)
        finally:
            if fd:
                fd.close()

class ScriptReader:
    def read(self, file_name):
        name = file_name.split('.')[-1]
        return Script(name, file_name)
        
class ScriptWriter:
    def write(self, script, destination_path):
        shutil.copy(script.path, destination_path)